# 导入日志模块
# EN: Import logging module
import logging
# 导入操作系统模块
# EN: Import os module
import os
# 导入时间模块
# EN: Import time module
import time
# 从 urllib.parse 模块导入 unquote 函数，用于 URL 解码
# EN: Import unquote function from urllib.parse module for URL decoding
from urllib.parse import unquote
# 导入 zipfile 模块，用于处理 zip 文件
# EN: Import zipfile module for handling zip files
import zipfile

# 从 myapp.const.base 模块导入 SharedMntDir 常量
# EN: Import SharedMntDir constant from myapp.const.base module
from myapp.const.base import SharedMntDir
# 从 myapp.utils 模块导入 strings 模块
# EN: Import strings module from myapp.utils module
from myapp.utils import strings
# 导入 requests 模块，用于发送 HTTP 请求
# EN: Import requests module for sending HTTP requests
import requests
# 导入 retry 模块，用于函数重试
# EN: Import retry module for function retries
import retry


# 获取名为 'get_annotation_info' 的 logger 实例，并设置其日志级别为 INFO
# EN: Get a logger instance named 'get_annotation_info' and set its log level to INFO
logging.getLogger('get_annotation_info').setLevel(logging.INFO)

# 从环境变量中获取标注系统的主机地址
# EN: Get the host address of the annotation system from environment variables
annotation_host = os.getenv('ANNOTATION_URL')
# 访问密钥
# EN: Access key
ak = 'YWIyZjBmMDIzNDYwYzgxZTdmZjU3MDMxNTY4NGNlZjI='
# 密钥
# EN: Secret key
sk = 'ZjJkMzA5MWIwNjQ4MDQ0ZWJmZTMxODQxNThkNGNmYmE='
# 获取标注信息的 URL 模板
# EN: URL template for getting annotation information
annotation_info_url = '{}/api/open/api/getAnnotationInfo?accessKey={}&timestamp={}&sign={}'
# 下载标注文件的 URL 模板
# EN: URL template for downloading annotation files
download_annotation_file_url = (
    '{}/api/open/api/downloadAnnotationFile?accessKey={}&timestamp={}&sign={}&taskId={}'
)


# 使用 retry 装饰器，设置重试次数为 3 次，延迟 1 秒
# EN: Use the retry decorator, set the number of retries to 3, with a delay of 1 second
@retry.retry(tries=3, delay=1)
def get_annotation_info(task_id=None, user_list=None, start_time=None, end_time=None):
    """
    获取标注信息
    EN: Get annotation information

    Args:
        task_id (str, optional): 任务 ID. Defaults to None.
        EN: task_id (str, optional): Task ID. Defaults to None.
        user_list (list, optional): 用户列表. Defaults to None.
        EN: user_list (list, optional): User list. Defaults to None.
        start_time (str, optional): 开始时间. Defaults to None.
        EN: start_time (str, optional): Start time. Defaults to None.
        end_time (str, optional): 结束时间. Defaults to None.
        EN: end_time (str, optional): End time. Defaults to None.

    Raises:
        Exception: 如果请求失败则抛出异常
        EN: Exception: Raise an exception if the request fails

    Returns:
        list: 包含标注信息的列表
        EN: list: A list containing annotation information
    """
    # 获取当前时间戳
    # EN: Get the current timestamp
    timestamp = int(time.time())
    # 构建请求参数
    # EN: Build request parameters
    params = {
        'user_ids': user_list,
        'start_time': start_time,
        'end_time': end_time,
        'template_type': '308,352',
        'status': 5,
    }
    # 构建请求 URL
    # EN: Build request URL
    url = annotation_info_url.format(
        annotation_host, ak, timestamp, strings.md5(ak + str(timestamp) + sk)
    )
    # 发送 POST 请求
    # EN: Send POST request
    resp = requests.post(url, json=params)
    # 检查响应状态码
    # EN: Check response status code
    if resp.status_code != 200:
        # 记录错误日志
        # EN: Log error message
        logging.info(f'{task_id} getAnnotationInfo 失败，reason:{resp.text}')
        # 抛出异常
        # EN: Raise exception
        raise Exception(f'{task_id} getAnnotationInfo失败，reason:{resp.text}')
    # 解析 JSON 响应
    # EN: Parse JSON response
    ret = resp.json()
    # 初始化结果列表
    # EN: Initialize result list
    res = []
    # 检查响应代码
    # EN: Check response code
    if ret.get('code') != 'SUCCESS':
        # 记录错误日志
        # EN: Log error message
        logging.info(f'{task_id} getAnnotationInfo失败,ret:{ret}')
        # 返回空列表
        # EN: Return empty list
        return res
    # 遍历响应数据
    # EN: Iterate through response data
    for ds in ret.get('data'):
        # 如果数据集不为空，则添加到结果列表中
        # EN: If the dataset is not empty, add it to the result list
        if len(ds.get('dataset')) > 0:
            res.append(ds)
    # 返回结果列表
    # EN: Return the result list
    return res


# 使用 retry 装饰器，设置重试次数为 3 次，延迟 1 秒
# EN: Use the retry decorator, set the number of retries to 3, with a delay of 1 second
@retry.retry(tries=3, delay=1)
def send_download_annotation_file(url):
    """
    发送下载标注文件的请求
    EN: Send a request to download the annotation file

    Args:
        url (str): 下载 URL
        EN: url (str): Download URL

    Raises:
        Exception: 如果请求失败则抛出异常
        EN: Exception: Raise an exception if the request fails

    Returns:
        requests.Response: 响应对象
        EN: requests.Response: Response object
    """
    # 发送 GET 请求
    # EN: Send GET request
    resp = requests.get(url, stream=True)
    # 检查响应状态码
    # EN: Check response status code
    if resp.status_code != 200:
        # 抛出异常
        # EN: Raise exception
        raise Exception(f'download_annotation_File失败，reason:{resp.text}')
    # 返回响应对象
    # EN: Return the response object
    return resp


def download_annotation_file(task_id, annotation_task_id, dataset_path):
    """
    下载并解压标注文件
    EN: Download and extract the annotation file

    Args:
        task_id (str): 任务 ID
        EN: task_id (str): Task ID
        annotation_task_id (str): 标注任务 ID
        EN: annotation_task_id (str): Annotation task ID
        dataset_path (str): 数据集路径
        EN: dataset_path (str): Dataset path

    Returns:
        int: 成功返回 1，失败返回 0
        EN: int: Return 1 for success, 0 for failure
    """
    try:
        # 获取当前时间戳
        # EN: Get the current timestamp
        timestamp = int(time.time())
        # 构建下载 URL
        # EN: Build download URL
        url = download_annotation_file_url.format(
            annotation_host,
            ak,
            timestamp,
            strings.md5(ak + str(timestamp) + sk),
            annotation_task_id,
        )
        # 发送下载请求
        # EN: Send download request
        resp = send_download_annotation_file(url)
        # 写入的文件路径 下载的是一个zip包
        # EN: The file path to write to, the downloaded file is a zip package
        file_path = SharedMntDir + dataset_path
        # 打印文件路径
        # EN: Print file path
        print(f'{task_id} download_annotation_File file_path: {file_path}')
        # 如果路径不存在，则创建
        # EN: If the path does not exist, create it
        if not os.path.exists(file_path):
            os.makedirs(file_path)
        # 获取 zip 文件路径
        # EN: Get the zip file path
        zip_path = file_path + unquote(
            resp.headers.get('Content-Disposition').split('=')[-1].strip().replace('"', '')
        )
        # 以二进制模式打开文件，准备写入
        # EN: Open the file in binary mode to prepare for writing
        with open(zip_path, 'wb') as f:
            # 循环读取响应内容，并写入文件
            # EN: Loop through the response content and write to the file
            for chunk in resp.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
        # 解压文件
        # EN: Unzip the file
        with zipfile.ZipFile(zip_path, 'r') as zip_ref:
            zip_ref.extractall(file_path)
        # 删除压缩文件
        # EN: Delete the compressed file
        os.remove(zip_path)
        # 打印成功信息
        # EN: Print success message
        print(f'{task_id} download_annotation_File cronjob run success')
        # 返回 1 表示成功
        # EN: Return 1 for success
        return 1
    except Exception as e:
        # 打印错误信息
        # EN: Print error message
        print(f'{task_id} download_annotation_File cronjob run error:', e)
        # 返回 0 表示失败
        # EN: Return 0 for failure
        return 0
